Swift Combine - Error
iOS Swift Combine Error Reactive Programming
這是一個基本的使用 Combine 的網路請求
func getData() -> AnyPublisher<Model, Error> {
    URLSession.shared.dataTaskPublisher(for: URL(string: "https://xxx.xx/xx")!)
        .map { $0.data }
        .decode(type: Model.self, decoder: JSONDecoder())
        .eraseToAnyPublisher()
}
看起來很正常,成功給 model,失敗給 model
問題是這個 func return 的 error 會有好幾種
以這個範例來說 會有 URLError DecodingError
實際 sink 的使用端,並不會知道這裡會出現多少種 error
合理的設計是要明確定義有多少種 error
例如 建立一個 ApiError
enum ApiError: Error {
    case url(error: URLError)
    case decode(error: Error)
}
再把 func 修改一下
func getData() -> AnyPublisher<Model, Error> {
    URLSession.shared.dataTaskPublisher(for: URL(string: "https://xxx.xx/xx")!)
        .mapError({ error in
            ApiError.url(error: error)
        })
        .map { $0.data }
        .decode(type: Model.self, decoder: JSONDecoder())
        .mapError({ error in
            if type(of: error) == ApiError.self {
                return error
            } else {
                return ApiError.decode(error: error)
            }
        })
        .eraseToAnyPublisher()
}
修改成這樣的確是達成了效果 但是會寫大量相同的 mapError
讓我們把大量相同的 mapError 換成自己定義的 operator
再修改一次 getData function
func getData() -> AnyPublisher<Model, ApiError> {
    URLSession.shared.dataTaskPublisher(for: URL(string: "https://xxx.xx/xx")!)
        .asError(type: ApiError.self, { .url(error: $0) })
        .map { $0.data }
        .decode(type: Model.self, decoder: JSONDecoder())
        .asError(type: ApiError.self, { .decode(error: $0)})
        .eraseToAnyPublisher()
}
這樣實作上,簡單許多,也更容易閱讀
打完收工